package cn.jserv.shutter;

import static cn.jserv.shutter.Const.FOCUS;
import static cn.jserv.shutter.Const.POWER_TOGGLE;
import static cn.jserv.shutter.Const.SHUTTER;
import static cn.jserv.shutter.Const.TIMELAPSE;
import static cn.jserv.shutter.Const.UN_FOCUS;
import static cn.jserv.shutter.Const.UN_TIMELAPSE;
import static cn.jserv.shutter.Const.UUID_CONFIG;
import static cn.jserv.shutter.Const.UUID_READ_CHARACTER;
import static cn.jserv.shutter.Const.UUID_SERVICE;
import static cn.jserv.shutter.Const.UUID_WRITE_CHARACTER;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.UUID;

public class ShutterActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {

    BluetoothDevice bluetoothDevice;

    BluetoothGatt bluetoothGatt;

    BluetoothGattService gattService;

    BluetoothGattCharacteristic readCharacteristic;

    BluetoothGattCharacteristic writeCharacteristic;

    boolean connectState = false;

    ProgressDialog progressDialog;

    ImageButton powerBtn;

    ImageButton modeBtn;

    ImageButton focusBtn;

    ImageButton shutterBtn;

    TextView bulbText;

    TextView intervalText;

    TextView totalText;

    TextView modeView;

    short timelapseTotal = 0;

    short timelapseInterval = 0;

    byte currentMode = 0;

    String[] currentModeString = {"单张拍摄", "BULB", "延时摄影"};

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        setContentView(R.layout.activity_shutter);
        Objects.requireNonNull(getSupportActionBar()).setElevation(0);
        Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
        progressDialog = new ProgressDialog(ShutterActivity.this);
        progressDialog.setIndeterminate(false);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.setMessage(getString(R.string.connect));
        progressDialog.setCancelable(false);
        bluetoothDevice = getIntent().getParcelableExtra("device");
        String deviceName = bluetoothDevice.getName().trim();
        getSupportActionBar().setTitle(deviceName);
        vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
        sharedPreferences = getSharedPreferences("params", MODE_PRIVATE);
        powerBtn = findViewById(R.id.btn_power);
        powerBtn.setOnClickListener(this);
        modeBtn = findViewById(R.id.btn_mode_switch);
        modeBtn.setOnClickListener(this);
        focusBtn = findViewById(R.id.btn_focus);
        focusBtn.setOnTouchListener(this);
        shutterBtn = findViewById(R.id.btn_shutter);
        shutterBtn.setOnClickListener(this);
        bulbText = findViewById(R.id.text_bulb);
        intervalText = findViewById(R.id.text_interval);
        totalText = findViewById(R.id.text_total);
        modeView = findViewById(R.id.mode);
        connect();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.about, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            vibrator.cancel();
            close();
            finish();
            return true;
        }
        if (item.getItemId() == R.id.action_about) {
            // TODO: 2022/5/30 0030 展示关于页面
        }
        return super.onOptionsItemSelected(item);
    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View view) {
        vibrator.vibrate(50);
        switch (view.getId()) {
            case R.id.btn_power:
                sendCmd(POWER_TOGGLE);
                break;
            case R.id.btn_mode_switch:
                changeMode();
                break;
            case R.id.btn_shutter:
//                <!--单张、1秒连拍、BULB、延时-->
                if (currentMode == 0) {
                    sendCmd(SHUTTER);
                } else if (currentMode == 1) {
                    if (timelapseInterval != 0) {
                        //B门是按住快门不放
                        byte intervalH = (byte) ((timelapseInterval & 0xFF00) >> 8);
                        byte intervalL = (byte) (timelapseInterval & 0x00FF);
                        byte[] bulbShutter = {(byte) 0xFF, (byte) 0xFE, 0x04, 0x00, 0x00, 0x00, intervalH, intervalL, 0x00, 0x00, (byte) 0xFE, (byte) 0xFF};
                        sendCmd(bulbShutter);
                    } else {
                        vibrator.vibrate(new long[]{50, 100, 50}, -1);
                        Toast.makeText(ShutterActivity.this, getString(R.string.title_param), Toast.LENGTH_SHORT).show();
                    }
                } else if (currentMode == 2) {
                    boolean isTimelapse = sharedPreferences.getBoolean("timelapse", false);
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    if (!isTimelapse) {
                        if (timelapseInterval != 0 && timelapseTotal != 0) {
                            sendCmd(timelapseCalc());
                            editor.putBoolean("timelapse", true);
                            editor.apply();
                        }
                    } else {
                        sendCmd(UN_TIMELAPSE);
                        editor.putBoolean("timelapse", false);
                        editor.apply();
                    }
                }
                break;
            default:
                break;
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (v.getId() == R.id.btn_focus) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                vibrator.vibrate(50);
                sendCmd(FOCUS);
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                vibrator.vibrate(new long[]{50, 100, 50}, -1);
                sendCmd(UN_FOCUS);
            }
        }
        return false;
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        vibrator.cancel();
        close();
    }

    private void connect() {
        bluetoothGatt = bluetoothDevice.connectGatt(this, false, gattCallback);
        progressDialog.show();
    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            progressDialog.dismiss();
            //连接状态改变时回调
            Log.d("BLE", String.valueOf(newState));
            super.onConnectionStateChange(gatt, status, newState);
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                connectState = true;
                bluetoothGatt.discoverServices();
            } else {
                //Can't toast on a thread that has not called Looper.prepare()
                connectState = false;
                gattService = null;
                close();
                finish();
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            Log.d("BLE", "发现服务");
            gattService = bluetoothGatt.getService(UUID.fromString(UUID_SERVICE));
            readCharacteristic = gattService.getCharacteristic(UUID.fromString(UUID_READ_CHARACTER));
            writeCharacteristic = gattService.getCharacteristic(UUID.fromString(UUID_WRITE_CHARACTER));
            bluetoothGatt.setCharacteristicNotification(readCharacteristic, true);
            BluetoothGattDescriptor descriptor = readCharacteristic.getDescriptor(UUID.fromString(UUID_CONFIG));
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            gatt.writeDescriptor(descriptor);
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            Log.d("BLE", "写入数据成功");
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            byte[] response = characteristic.getValue();
            Log.d("BLE", "接收快门返回数据=" + Arrays.toString(response));
            if (response[2] == 0x05 && response[3] == 0x01) {
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putBoolean("timelapse", true);
                editor.apply();
                int total = ((int) response[4] & 0xFF) << 8 | response[5];
                int interval = ((int) response[6] & 0xFF) << 8 | response[7];
                int setTotal = sharedPreferences.getInt("total", 0);
                ShutterActivity.this.runOnUiThread(() -> {
                    currentMode = 2;
                    modeView.setText(getString(R.string.mode_timelapse));
                    totalText.setText(String.format(Locale.CHINA, "%d/%d", total, setTotal));
                    intervalText.setText(String.format(getString(R.string.seconds), interval));
                });
            }
        }

    };

    private void changeMode() {
        currentMode++;
        if (currentMode == 3) {
            currentMode = 0;
        }
        modeView.setText(currentModeString[currentMode]);
        if (currentMode == 1 || currentMode == 2) {
            CustomDialog dialog = new CustomDialog(ShutterActivity.this);
            dialog.setMode(currentMode).setCancel(v -> {
                timelapseInterval = 0;
                timelapseTotal = 0;
                dialog.dismiss();
            }).setConfirm(v -> {
                if (currentMode == 1) {
                    timelapseInterval = Short.parseShort(dialog.getBulbTimeEditText().getText().toString());
                    bulbText.setText(String.format(getString(R.string.seconds), timelapseInterval));
                } else if (currentMode == 2) {
                    timelapseInterval = Short.parseShort(dialog.getIntervalEditText().getText().toString());
                    timelapseTotal = Short.parseShort(dialog.getTotalEditText().getText().toString());
                    intervalText.setText(String.format(getString(R.string.seconds), timelapseInterval));
                    totalText.setText(String.format(Locale.CHINA, "%d/%d", 0, timelapseTotal));
                    SharedPreferences.Editor edit = sharedPreferences.edit();
                    edit.putInt("total", timelapseTotal);
                    edit.putInt("interval", timelapseInterval);
                    edit.apply();
                }
                dialog.dismiss();
            }).show();
        }
    }

    private void sendCmd(byte[] body) {
        if (connectState) {
            writeCharacteristic.setValue(body);
            bluetoothGatt.writeCharacteristic(writeCharacteristic);
        }
    }

    private void close() {
        if (null != bluetoothGatt) {
            bluetoothGatt.disconnect();
            bluetoothGatt.close();
            bluetoothGatt = null;
            connectState = false;
        }
    }

    private Vibrator vibrator;

    SharedPreferences sharedPreferences;

    private byte[] timelapseCalc() {
        TIMELAPSE[4] = (byte) ((timelapseTotal & 0xFF00) >> 8);
        TIMELAPSE[5] = (byte) (timelapseTotal & 0x00FF);
        TIMELAPSE[6] = (byte) ((timelapseInterval & 0xFF00) >> 8);
        TIMELAPSE[7] = (byte) (timelapseInterval & 0x00FF);
        for (byte i = 0; i < 8; i++) {
            Log.d("SEND", String.format("%02x ", TIMELAPSE[i]));
        }
        return TIMELAPSE;
    }
}